package br.com.usapre.faces;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaFactory;
import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import br.com.bean.CadastroInicial;
import br.com.business.ParceiroBusiness;
import br.com.business.TipoUsuarioBusiness;
import br.com.data.Parceiro;
import br.com.data.TipoUsuario;
import br.com.data.Usuario;
import br.com.exception.ValidacaoCaptchaException;
import br.com.login.business.LogSistemaBusiness;
import br.com.login.business.LoginBusiness;
import br.com.login.business.UsuarioBusiness;
import br.com.login.faces.SessionUsaPreBean;
import br.com.utilidades.criptografia.MD5Criptografia;
import br.com.utilidades.database.data.Criterio;
import br.com.utilidades.faces.SimpleMessageBean;
import constantes.CONSTANTES;

/**
 * @version 1.0.0
 * @since Janeiro,29 2013
 * @author Eduardo Francisco Barbosa
 */
@Component
@Scope("view")
public class CadastroBean extends SimpleMessageBean implements Serializable {

    private static final long serialVersionUID = 2362006665233518664L;

    private UsuarioBusiness usuarioBusinessImpl;
    private TipoUsuarioBusiness tipoUsuarioBusinessImpl;
    private ParceiroBusiness parceiroBusinessImpl;

    @Autowired
    private LoginBusiness loginBusinessImpl;
    @Autowired
    private LogSistemaBusiness logSistemaBusinessImpl;

    private SessionUsaPreBean sessionUsaPreBean;

    private CadastroInicial cadastroInicial;

    private String email;
    private String senha;

    private Usuario novoUsuario;

    /**
     * Construtor
     */
    @Autowired
    public CadastroBean(TipoUsuarioBusiness tipoUsuarioBusinessImpl, UsuarioBusiness usuarioBusinessImpl,
	    SessionUsaPreBean sessionUsaPreBean, ParceiroBusiness parceiroBusinessImpl) {

	this.sessionUsaPreBean = sessionUsaPreBean;
	this.tipoUsuarioBusinessImpl = tipoUsuarioBusinessImpl;
	this.usuarioBusinessImpl = usuarioBusinessImpl;
	this.parceiroBusinessImpl = parceiroBusinessImpl;

	reset();
    }

    /**
     * reset
     */
    public void reset() {

	cadastroInicial = new CadastroInicial();
    }

    /**
     * cadastrar
     */
    public void cadastrar() {

	String resultado = processaImagem();

	if (resultado.equals("invalido") || resultado.equals("erro")) {
	    String msgCaptcha = super.getMensagem("MN_captcha_invalido");
	    enviaMensagem(msgCaptcha, msgCaptcha);
	}

	if (resultado.equals("correto")) {

	    // <f:validateRegex
	    // pattern="[\w\.-]*[a-zA-Z0-9_]@[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]"
	    // />
	    // requiredMessage="Campo confirmação email é obrigatório"
	    // validatorMessage="Formato de email inválido"

	    if (!cadastroInicial.getEmail().equals("")) {

		if (cadastroInicial.getEmail().equals(cadastroInicial.getConfirmaEmail())) {

		    if (cadastroInicial.getAceiteTermoseCondicoes()) {

			Usuario usu = usuarioBusinessImpl.buscarUsuarioPorEmail(cadastroInicial.getEmail());

			if (usu == null) {

			    if (validarUsuario(cadastroInicial.getNomeUsuario())) {

				if (cadastroInicial.getSenha().equals(cadastroInicial.getConfirmacaoSenha())) {

				    List<Criterio> criterios = new ArrayList<Criterio>();

				    Criterio crit = new Criterio();
				    crit.setCampo("nomeUsuario");
				    crit.setComparacao("like");
				    crit.setTipo(Criterio.TIPO_STRING_CASE_SENSITIVE);
				    crit.setValue(cadastroInicial.getNomeUsuario());
				    criterios.add(crit);

				    List<Parceiro> loginParceirosIguais = parceiroBusinessImpl.buscarPorCriterios(
					    criterios, "");
				    List<Usuario> loginUsuariosIguais = usuarioBusinessImpl.buscarPorCriterios(
					    criterios, "");

				    if (loginParceirosIguais.size() > 0 || loginUsuariosIguais.size() > 0) {

					String msg = super.getMensagem("MN_nome_usuario_indisponivel");
					enviaMensagem(msg, msg);

				    } else {

					try {

					    TipoUsuario tipoUsuario = tipoUsuarioBusinessImpl.buscarPorId(1);

					    novoUsuario = new Usuario();

					    novoUsuario.setAtivo(Boolean.TRUE);
					    novoUsuario.setEmail(cadastroInicial.getEmail());
					    novoUsuario.setNome(cadastroInicial.getNome());
					    novoUsuario.setNomeUsuario(cadastroInicial.getNomeUsuario());
					    if (CONSTANTES.CRIPTOGRAFADO) {
						novoUsuario.setSenha(MD5Criptografia.criptografa(cadastroInicial
							.getSenha()));
					    } else {
						novoUsuario.setSenha(cadastroInicial.getSenha());
					    }
					    novoUsuario.setTipoUsuario(tipoUsuario);
					    novoUsuario.setOrigemUsuario("USA-PRÉ-INCOMPLETO");
					    novoUsuario.setDataCadastro(new Date());

					    usuarioBusinessImpl.salvar(novoUsuario);

					    sessionUsaPreBean.setLogado(Boolean.TRUE);
					    sessionUsaPreBean.setUsuario(novoUsuario);

					    try {
						FacesContext
							.getCurrentInstance()
							.getExternalContext()
							.redirect(
								"/" + CONSTANTES.URLUSAPRE
									+ "/homeFinalizaCadastro.jsf");
					    } catch (Exception ex) {
						ex.printStackTrace();
					    }

					} catch (Exception e) {
					    String msgErroSalvar = super.getMensagem("MN_erro_salvar_usuario");
					    enviaMensagem(msgErroSalvar, msgErroSalvar);
					}
				    }

				} else {
				    String msgSenhaNaoConfere = super.getMensagem("MN_senha_nao_confere");
				    enviaMensagem(msgSenhaNaoConfere, msgSenhaNaoConfere);
				}
			    } else {
				String msgCaracterIlegal = super.getMensagem("MN_existem_caracter_especial");
				enviaMensagem(msgCaracterIlegal, msgCaracterIlegal);
			    }
			} else {
			    String msgEmailJaExiste = super.getMensagem("MN_email_ja_existe");
			    enviaMensagem(msgEmailJaExiste, msgEmailJaExiste);
			}
		    } else {
			String msgAceitarTermosCondicoes = super.getMensagem("MN_aceitar_termos_condicoes");
			enviaMensagem(msgAceitarTermosCondicoes, msgAceitarTermosCondicoes);
		    }
		} else {
		    String msgEmailNaoConfere = super.getMensagem("MN_email_nao_confere");
		    enviaMensagem(msgEmailNaoConfere, msgEmailNaoConfere);
		}
	    } else {
		String msgEmailObrigatorio = super.getMensagem("MN_email_campo_obrigatorio");
		enviaMensagem(msgEmailObrigatorio, msgEmailObrigatorio);
	    }
	}
    }

    /**
     * validarUsuario
     * 
     * metodo responsavel por bloquear caracteres indesejados no usuario
     * 
     * @return Boolean
     */
    public Boolean validarUsuario(String nomeUsuario) {

	Boolean liberado = Boolean.TRUE;
	int a = 0;
	while (a < nomeUsuario.length()) {

	    char caracter = nomeUsuario.charAt(a);

	    if ((caracter > 58 && caracter < 126) || (caracter > 47 && caracter < 58)) {

	    } else {
		liberado = Boolean.FALSE;
	    }

	    a++;
	}

	return liberado;
    }

    /**
     * Gera o código HTML gerado pelo componente da Google.
     * 
     * @return String - código HTML dinâmico
     */
    public String getCodigoHtmlRecaptcha() {

	// ReCaptcha para o seguinte dominio: usacard.ddns.com.br
	// ReCaptcha c =
	// ReCaptchaFactory.newReCaptcha("6LeJZeMSAAAAAJeTwq3QP2Ig677R_-jkRDB4WTBH",
	// "6LeJZeMSAAAAAHejpSbEiSFJdAxNfqIazCtIn3Xx", false);

	ReCaptcha c = ReCaptchaFactory.newReCaptcha("6LePZeMSAAAAADPiu2We0mVTk-JtOcC5vHX7E8ZQ",
		"6LePZeMSAAAAAO5x8j2lB7rCXzsn-uzAEzrL4k6r", false);

	// ReCaptcha para o seguinte dominio: 200.163.74.40
	// ReCaptcha c =
	// ReCaptchaFactory.newReCaptcha("6Lfz5N4SAAAAAIHR6Xqd1YOn5mQYcgjaJko1XN6x",
	// "6Lfz5N4SAAAAALtTOQAvPlvebF5GTRjaZ2wIONxq", false);

	return c.createRecaptchaHtml(null, null);
    }

    /**
     * Gera o código HTML gerado pelo componente da Google.
     * 
     * @return String - código HTML dinâmico
     */
    public String processaImagem() {
	try {
	    if (!validaTextoImagem()) {
		return "invalido";
	    }
	} catch (ValidacaoCaptchaException e) {
	    e.printStackTrace();
	    return "erro";
	}
	return "correto";
    }

    /**
     * Valida o texto da imagem digitado pelo usuário.
     * 
     * @return boolean indicando se o texto foi validado ou não
     * 
     * @throws ValidacaoCaptchaException
     *             caso o componente não tenha sido exibido corretamente
     */
    private boolean validaTextoImagem() throws ValidacaoCaptchaException {
	HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
		.getRequest();
	String enderecoRemoto = req.getRemoteAddr();
	ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
	reCaptcha.setPrivateKey("6LePZeMSAAAAAO5x8j2lB7rCXzsn-uzAEzrL4k6r");

	String textoCriptografado = req.getParameter("recaptcha_challenge_field");
	String resposta = req.getParameter("recaptcha_response_field");

	/**
	 * Testa se o campo desafio está nulo ou vazio, ou se o campo resposta
	 * veio nulo (vem String vazia se o usuário não preencheu) e lança
	 * exception.
	 */
	if (textoCriptografado == null || textoCriptografado.equals("") || resposta == null) {
	    throw new ValidacaoCaptchaException(
		    "Dados submetidos não recuperados. Talvez exista um problema na exibição do componente captcha.");
	}

	ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(enderecoRemoto, textoCriptografado, resposta);

	if (resposta.isEmpty() || !reCaptchaResponse.isValid()) {
	    return false; // resposta em branco ou inválida
	} else {
	    return true; // texto válido
	}
    }

    // SETS AND GETS
    public CadastroInicial getCadastroInicial() {
	return cadastroInicial;
    }

    public void setCadastroInicial(CadastroInicial cadastroInicial) {
	this.cadastroInicial = cadastroInicial;
    }

    public String getEmail() {
	return email;
    }

    public void setEmail(String email) {
	this.email = email;
    }

    public String getSenha() {
	return senha;
    }

    public void setSenha(String senha) {
	this.senha = senha;
    }

    public LoginBusiness getLoginBusinessImpl() {
	return loginBusinessImpl;
    }

    public void setLoginBusinessImpl(LoginBusiness loginBusinessImpl) {
	this.loginBusinessImpl = loginBusinessImpl;
    }

    public LogSistemaBusiness getLogSistemaBusinessImpl() {
	return logSistemaBusinessImpl;
    }

    public void setLogSistemaBusinessImpl(LogSistemaBusiness logSistemaBusinessImpl) {
	this.logSistemaBusinessImpl = logSistemaBusinessImpl;
    }

}
